package cloud.gateway.web.route;

import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import cloud.gateway.web.entity.GatewayFilterDefinition;
import cloud.gateway.web.entity.GatewayPredicateDefinition;
import cloud.gateway.web.entity.GatewayRouteDefinition;
import cloud.gateway.web.service.DynamicRouteService;

import com.alibaba.fastjson.JSON;

/**
 * 定时任务，拉取路由信息 路由信息由路由项目单独维护
 * 日后改为mq处理方式
 * 思路：有后台添加路由后通过mq通知这边来处理redis
 */
@Component
public class DynamicRouteScheduling {
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
	private DynamicRouteService dynamicRouteService;

	
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final String dynamicRouteServerName = "cloud-admin-gateway";

    //发布路由信息的版本号
    private static Long versionId = 0L;

    //每60秒中执行一次
    //如果版本号不相等则获取最新路由信息并更新网关路由
    @Scheduled(cron = "*/60 * * * * ?")
    public void getDynamicRouteInfo(){
        try{
            System.out.println("拉取时间:" + dateFormat.format(new Date()));
            //先拉取版本信息，如果版本号不想等则更新路由
            Long resultVersionId = restTemplate.getForObject("http://"+ dynamicRouteServerName +"/version/lastVersion" , Long.class);
            System.out.println("路由版本信息：本地版本号：" + versionId + "，远程版本号：" + resultVersionId);
            if(resultVersionId != null && versionId != resultVersionId){
                System.out.println("开始拉取路由信息......");
                String resultRoutes = restTemplate.getForObject("http://"+ dynamicRouteServerName +"/gateway-routes/routes" , String.class);
                System.out.println("路由信息为：" + resultRoutes);
                if(!StringUtils.isEmpty(resultRoutes)){
                    List<GatewayRouteDefinition> list = JSON.parseArray(resultRoutes , GatewayRouteDefinition.class);
                    for(GatewayRouteDefinition definition : list){
                        //更新路由
                        RouteDefinition routeDefinition = assembleRouteDefinition(definition);
                        dynamicRouteService.update(routeDefinition);
                    }
                    versionId = resultVersionId;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

	private RouteDefinition assembleRouteDefinition(
			GatewayRouteDefinition gatewayDefinition) {
		RouteDefinition definition = new RouteDefinition();
        definition.setId(gatewayDefinition.getId());
        definition.setOrder(gatewayDefinition.getOrder());
        
        //设置断言
        List<PredicateDefinition> pdList = new ArrayList<>();
        List<GatewayPredicateDefinition> gatewayPredicateDefinitionList=gatewayDefinition.getPredicates();
        for (GatewayPredicateDefinition gatewayPredicateDefinition : gatewayPredicateDefinitionList) {
			PredicateDefinition predicate = new PredicateDefinition();
            predicate.setArgs(gatewayPredicateDefinition.getArgs());
            predicate.setName(gatewayPredicateDefinition.getName());
            pdList.add(predicate);
		}
		definition.setPredicates(pdList);
		
		//设置过滤器
		List<FilterDefinition> filters = new ArrayList<FilterDefinition>();
		List<GatewayFilterDefinition>  gatewayFilters = gatewayDefinition.getFilters();
		for (GatewayFilterDefinition gatewayFilterDefinition : gatewayFilters) {
            FilterDefinition filter = new FilterDefinition();
            filter.setName(gatewayFilterDefinition.getName());
            filter.setArgs(gatewayFilterDefinition.getArgs());
            filters.add(filter);
		}
		definition.setFilters(filters);
        URI uri = null;
        if(gatewayDefinition.getUri().startsWith("http")){
            uri = UriComponentsBuilder.fromHttpUrl(gatewayDefinition.getUri()).build().toUri();
        }else{
            uri = URI.create(gatewayDefinition.getUri());
        }
        definition.setUri(uri);
        return definition;
	
	}

    
}
